package cn.ad.server.job.adapter.persistence.job;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.annotation.Resource;

import cn.ad.server.job.adapter.dbaccess.DbDataContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Repository;

import cn.ad.server.job.adapter.dbaccess.AssembledCachedDataContainer;
import cn.ad.server.domain.ad.AdMaterial;
import cn.ad.server.domain.ad.AdMaterialGroup;
import cn.ad.server.domain.ad.AdSize;
import cn.ad.server.domain.ad.AdTemplateSpec;
import cn.ad.server.domain.ad.AppClass;
import cn.ad.server.domain.ad.Campaign;
import cn.ad.server.domain.ad.Creative;
import cn.ad.server.domain.ad.InteractionApp;
import cn.ad.server.domain.ad.InteractionRedirects;
import cn.ad.server.job.domain.job.CreativeWarmUpService;
import cn.ad.server.domain.enumration.AdFormat;

@Repository
public class CreativeWarmUpServant implements CreativeWarmUpService {

	private static Logger logger = LoggerFactory.getLogger(CreativeWarmUpServant.class);

	@Resource(name = "cacheRedisTemplate")
	private ValueOperations<String, Creative> creativesValueOperations;

	@Resource(name = "cacheRedisTemplate")
	private ValueOperations<String, Campaign> campaignValueOperations;

	@Resource(name = "cacheRedisTemplate")
	private RedisTemplate<String, String> redisTemplate;

	@Autowired
	private AssembledCachedDataContainer container;

	public void cachedAdCreativeByCampaign() {
		List<Creative> creatives = DbDataContainer.getCreativeAll();//全表-copy
		if (creatives == null) {
			return;
		}
		ConcurrentHashMap<Integer, CopyOnWriteArraySet<Creative>> mapper = container.getCreativesByCampaignIdMap();//存放的是有效的数据。
		for (Creative c : creatives) {
			try {
				mapper.putIfAbsent(c.getCampaignId(), new CopyOnWriteArraySet<Creative>());
				if (c.getStatus() == 1) {
					CopyOnWriteArraySet<Creative> copyOnWriteArraySet = mapper.get(c.getCampaignId());
					copyOnWriteArraySet.remove(c);
					copyOnWriteArraySet.add(c);
					upToRedis(c.getCampaignId(), c, true);
				} else {
					mapper.get(c.getCampaignId()).remove(c);
					upToRedis(c.getCampaignId(), c, false);
				}

			} catch (Exception e) {
				if (c != null) {
					logger.error("错误：在获取Creative_id =" + c.getId() + "数据时发生错误 \n 错误信息：", e);
				}
			}
		}
	}

	public void warmUpAdCreativeByCampaign() {
		cachedAdCreativeByCampaign();
		cachedAdMaterial();
		cachedAdMaterialGroup();
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterialGroup>> creativeMapToAdMaterialGroupMapper = container
				.getAdMaterialGroupsByCreativeIdMap();
		ConcurrentHashMap<Integer, CopyOnWriteArraySet<Creative>> campaignMapToCreativeMapper = container
				.getCreativesByCampaignIdMap();
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterial>> creativeMapToAdMaterialMapper = container
				.getAdMaterialsByCreativeIdMap();
		List<Campaign> campaignAll = DbDataContainer.getCampaignAll();//全表-copy
		long currentTimeMillis = System.currentTimeMillis();
		for (Campaign campaign : campaignAll) {
			if (campaign.getStatus() == 1) {
				Date endTime = campaign.getEndTime();
				if(endTime.getTime()<=currentTimeMillis){//当订单投放结束时不需要加载数据。
					redisTemplate.delete(campaign.toCacheKey());
				}else{					
					campaign.setCreatives(campaignMapToCreativeMapper.get(campaign.getId()));
					if (campaign.getCreatives() != null) {
						Set<Creative> creatives = campaign.getCreatives();
						//加入素材或素材组。
						for (Creative creative : creatives) {
							attachInteraction(creative);
							if(creative.getAdFormat()==AdFormat.AD_NATIVE){	//							
								creative.setAdMaterialGroupSet(creativeMapToAdMaterialGroupMapper.get(creative.getId()));
							}else{
								creative.setAdMaterialSet(creativeMapToAdMaterialMapper.get(creative.getId()));
							}
						}
					}
					campaignValueOperations.set(campaign.toCacheKey(), campaign);
				}
			} else {
				redisTemplate.delete(campaign.toCacheKey());
			}
		}
	}
	
	/**
	 * 创意添加交互。
	 * @param creative Creative
	 */
	private void attachInteraction(Creative creative) {
		if(creative==null){
			return;
		}
		// 0 无交互 1 跳转 2 APP下载 3
		
//		if(creative.getId()==608l){
//			System.out.println("");
//		}
		if (creative.getInteractionType() == 1) {
			InteractionRedirects interactionRedirect = DbDataContainer.getInteractionRedirect(creative.getInteractionId());
			creative.setInteractionRedirects(interactionRedirect);
		} else if (creative.getInteractionType() == 2) {
			InteractionApp interactionApp = DbDataContainer.getInteractionApp(creative.getInteractionId());
			if (interactionApp != null) {
				// 默认取两级
				AppClass appClass = DbDataContainer.getAppClass(interactionApp.getClassesId());

				interactionApp.setAppClass(appClass);
				if (appClass != null && appClass.getParentId() != 0) {
					AppClass parentAppClass = DbDataContainer.getAppClass(appClass.getParentId());
					appClass.setParentAppClass(parentAppClass);
				}
			}
			creative.setInteractionApp(interactionApp);
		}		
	}

	@Value("${cached.redisDebug:false}")
	private boolean redisDebug;

	void upToRedis(Integer cId, Creative c, boolean operatorFlg) {
		if (!redisDebug) {
			return;
		}
		String key = "CreativesByCampaignId:" + cId + ":" + c.getId();
		if (operatorFlg) {
			creativesValueOperations.set(key, c);
		} else {
			redisTemplate.delete(key);
		}
	}
	// --------------AdMaterial 相关的--------------
	private void cachedAdMaterial() {
		List<AdMaterial> mapAdms = DbDataContainer.getAdMaterialAll();// 全表-copy
		if (mapAdms == null) {
			return;
		}
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterial>> mapper = container.getAdMaterialsByCreativeIdMap();//存放有效数据。
		ConcurrentHashMap<Long, AdMaterial> adMaterials = container.getAdMaterials();
		for (AdMaterial am : mapAdms) {
			try {
				am.setCreative(null);
				mapper.putIfAbsent(am.getCreativeId(), new CopyOnWriteArraySet<AdMaterial>());
				if (am.getStatus() == 1) {
					am = attachAdSize(am);
					if (am != null) {
						CopyOnWriteArraySet<AdMaterial> copyOnWriteArraySet = mapper.get(am.getCreativeId());
						copyOnWriteArraySet.remove(am);
						copyOnWriteArraySet.add(am);
						adMaterials.put(am.getId(), am);
					}
				} else if (am.getStatus() != 1) {
					adMaterials.remove(Long.valueOf(am.getId()));
					mapper.get(am.getCreativeId()).remove(am);
				}
			} catch (Exception e) {
				if (am != null) {
					logger.error("错误：在获取AdMaterial_id =" + am.getId() + "数据时发生错误 \n 错误信息：", e);
				}
			}
		}
	}

	/**
	 * 附上adsize
	 * 
	 * @param adMaterial
	 * @return
	 */
	private AdMaterial attachAdSize(AdMaterial adMaterial) {
		if (adMaterial == null) {
			return null;
		}
		// adSize
		AdSize adSize = adMaterial.getAdSize();
		if (adSize != null) {
			adSize = DbDataContainer.getAdSize(adMaterial.getAdSize().getId());
			adMaterial.setAdSize(adSize);
		}
		return adMaterial;
	}

	// --------------AdMaterialGroup 相关的--------------
	private void cachedAdMaterialGroup() {
		List<AdMaterialGroup> adMaterialGroups = DbDataContainer.getAdMaterialGroupAll();//全表-copy
		if (adMaterialGroups == null) {
			return;
		}
		ConcurrentHashMap<Long, CopyOnWriteArraySet<AdMaterialGroup>> mapper = container.getAdMaterialGroupsByCreativeIdMap();//存放有效数据。
		for (AdMaterialGroup admg : adMaterialGroups) {
			try {
				admg.setCreative(null);
				mapper.putIfAbsent(admg.getCreativeId(), new CopyOnWriteArraySet<AdMaterialGroup>());
				if (admg.getStatus() == 1) {
					attachSomething(admg);
					CopyOnWriteArraySet<AdMaterialGroup> copyOnWriteArraySet = mapper.get(admg.getCreativeId());
					copyOnWriteArraySet.remove(admg);
					copyOnWriteArraySet.add(admg);
				} else {
					mapper.get(admg.getCreativeId()).remove(admg);
				}
			} catch (Exception e) {
				if (admg != null) {
					logger.error("错误：在获取AdMaterialGroup_id =" + admg.getId() + "数据时发生错误 \n 错误信息：", e);
				}
			}
		}
	}
	/**
	 * 附上 AdMaterial AdTemplateSpec InteractionRedirects InteractionApp AppClass 对象。
	 * @param admg
	 * @return
	 */
	private AdMaterialGroup attachSomething(AdMaterialGroup admg) {
		
		if(admg==null){
			return null;
		}
		AdMaterialGroup adMaterialGroup = admg;
		AdMaterial adMaterial = adMaterialGroup.getAdMaterial();
		if (adMaterial != null) {
			adMaterial = DbDataContainer.getAdMaterial(adMaterial.getId());//copy
			if(adMaterial!=null){
				adMaterial.setCreative(null);
			}
			adMaterialGroup.setAdMaterial(adMaterial);
		} else {
			adMaterialGroup.setAdMaterial(null);
		}

		AdTemplateSpec adTemplateSpec = adMaterialGroup.getAdTemplateSpec();
		if (adTemplateSpec != null) {
			adTemplateSpec = DbDataContainer.getAdTemplateSpec(adTemplateSpec.getId());//copy
			adMaterialGroup.setAdTemplateSpec(adTemplateSpec);
		} else {
			adMaterialGroup.setAdTemplateSpec(null);
		}

		// 0 无交互 1 跳转 2 APP下载 3
		if (adMaterialGroup.getInteractionType() == 1) {
			InteractionRedirects interactionRedirect = DbDataContainer.getInteractionRedirect(adMaterialGroup.getInteractionId());
			adMaterialGroup.setInteractionRedirects(interactionRedirect);
		} else if (adMaterialGroup.getInteractionType() == 2) {
			InteractionApp interactionApp = DbDataContainer.getInteractionApp(adMaterialGroup.getInteractionId());
			if (interactionApp != null) {
				// 默认取两级
				AppClass appClass = DbDataContainer.getAppClass(interactionApp.getClassesId());//copy

				interactionApp.setAppClass(appClass);
				if (appClass != null && appClass.getParentId() != 0) {
					AppClass parentAppClass = DbDataContainer.getAppClass(appClass.getParentId());//copy

					appClass.setParentAppClass(parentAppClass);
				}
			}
			adMaterialGroup.setInteractionApp(interactionApp);
		}

		return adMaterialGroup;
	}
	
}
